// Written by Steve Andersen, copyright (c) 2007 ONE/Northwest
// This program is released under the GNU General Public License. http://www.gnu.org/licenses/

public class HouseholdMaintenance {
	
	//Map to hold Households to be processed
	private Map<Id,ONEN_Household__c> HouseholdsMap = new Map<Id,ONEN_Household__c>();
	//Map to hold HousholdId and a list of related Contacts	
	private Map<Id,List<Contact>> HouseholdsWithContacts = new Map<Id,List<Contact>>();
	//list of Contacts for a specific Household
	private List<Contact> ContactsInHouseholds = new List<Contact>();	
	//list of Contacts to be updated
	private Map<Id,Contact> ContactsForUpdate = new Map<Id,Contact>();

	//constructor
	public HouseholdMaintenance(Map<Id,ONEN_Household__c> TheseHouseholds) {
		//we used to assign the value of the map this way:
		//HouseholdsMap = TheseHouseholds;
		//but that set the maps to be references to eachother, which caused changes that happen in the method
		//to change the map in the calling trigger, which was hella confusing
		
		for ( id thisId : TheseHouseholds.keyset() ) {
			HouseholdsMap.put ( thisId , TheseHouseholds.get(thisId) );	
		}
		
		//create a list of Contacts that are members of that Household
		if(HouseholdsMap.size()>0) {
			ContactsInHouseholds = [select Id, FirstName, LastName,ONEN_Household__c,MailingStreet,MailingCity,MailingState,MailingPostalCode,MailingCountry from Contact where ONEN_Household__c IN :HouseholdsMap.keySet() Order by ONEN_Household__c asc, LastName asc, FirstName asc];
		}
	}
	
	//public method for getting the Contacts in the Housholds
	public List<Contact> getContactsInHouseholds() {
		return ContactsInHouseholds;
	}
	
	//public method for getting the Housholds to be updated
	public List<ONEN_Household__c> getHouseholdsForUpdate() {
		return HouseholdsMap.values();
	}
	
	//public method to create Households for a list of Contacts that need them
	public void createNewHouseholds(List<Contact> ContactsWithNoHousehold) {
		List<ONEN_Household__c> newHouseholds = new List<ONEN_Household__c>();
		//a list of Names for Households for new Contacts
	    List<String> ContactsWithNoHouseholdsHouseholdName = new List<String>();
	    //a list of Greetings for Households for new Contacts
	    List<String> ContactsWithNoHouseholdsGreeting = new List<String>();
		//variables for household naming
		String HouseholdName;	
		String Greeting;
		String FirstName;
		String LastName;
		//loop through the Contacts
		for (Contact ContactNeedingHousehold : ContactsWithNoHousehold) {  			
			//get the names
			FirstName = ContactNeedingHousehold.firstname;
			LastName = ContactNeedingHousehold.lastname;
			//create the Household Name
			if(FirstName!=null) {
				HouseholdName = ContactNeedingHousehold.firstname + ' ' + ContactNeedingHousehold.lastname;
			} else {
				HouseholdName = ContactNeedingHousehold.lastname;
			}
			//add the name to the list of Household Names
			ContactsWithNoHouseholdsHouseholdName.add(HouseholdName);
			
			//handle the case when fistname doesn't exist
			if(FirstName!=null) {
				Greeting = FirstName;
			} else {
				Greeting = 'Friend';
			}
			//add the greeting to the list of Greetings
			ContactsWithNoHouseholdsGreeting.add(Greeting);
			//create the household object	
						
			ONEN_Household__c hh = new ONEN_Household__c (				
				Name=HouseholdName,
				Greeting__c=Greeting,				
				MailingStreet__c=ContactNeedingHousehold.MailingStreet,
				MailingCity__c=ContactNeedingHousehold.MailingCity,
				MailingState__c=ContactNeedingHousehold.MailingState,
				MailingPostalCode__c=ContactNeedingHousehold.MailingPostalCode,
				MailingCountry__c=ContactNeedingHousehold.MailingCountry,
				Member_Count__c=1		
			);
			//add the Household to the list of Households to be inserted
			newHouseholds.add(hh);
		}
		//if there are Households to be created		
		if(newHouseholds.size()>0){

			try {
				//create them
				insert newHouseholds;
			} catch (System.DmlException e) {		
				for (Integer k = 0; k < e.getNumDml(); k++) {
				 System.debug(e.getDmlMessage(k)); 
				}
			}
			//loop through the new Households and put them in the map
			for(ONEN_Household__c updatedHH : newHouseholds) {
				HouseholdsMap.put(updatedHH.Id,updatedHH);
			}
			
			//variable to iterate through a list
			Integer ContactListCounter;
			ContactListCounter=0;
			//loop through the Contacts that don't have Households and update their Household Names and Greetings
			for (Contact ContactNeedingHousehold : ContactsWithNoHousehold) {	
				ContactNeedingHousehold.ONEN_Household__c = NewHouseholds[ContactListCounter].id;
				ContactNeedingHousehold.Household_Greeting__c=ContactsWithNoHouseholdsGreeting[ContactListCounter];
				ContactNeedingHousehold.Household_Name__c=ContactsWithNoHouseholdsHouseholdName[ContactListCounter];
				ContactListCounter++;
			}
		}		
	}
	public void putContactAddressOnHousehold(List<Contact> ContactsWithHouseholdsWithGoodAddress) {
		List<ONEN_Household__c> householdsForUpdating = new List<ONEN_Household__c>();
		for (Contact contactWithGoodAddress : ContactsWithHouseholdsWithGoodAddress) {
			ONEN_Household__c hh = new ONEN_Household__c (
				id=contactWithGoodAddress.ONEN_Household__c,				
				MailingStreet__c=contactWithGoodAddress.MailingStreet,
				MailingCity__c=contactWithGoodAddress.MailingCity,
				MailingState__c=contactWithGoodAddress.MailingState,
				MailingPostalCode__c=contactWithGoodAddress.MailingPostalCode,
				MailingCountry__c=contactWithGoodAddress.MailingCountry
			);
			//add the Household to the list of Households to be inserted
			householdsForUpdating.add(hh);
			
		}
		if(householdsForUpdating.size()>0){
			try {
				//create them
				update householdsForUpdating;
			} catch (System.DmlException e) {		
				for (Integer k = 0; k < e.getNumDml(); k++) {
				 System.debug(e.getDmlMessage(k)); 
				}
			}
		}
	}
	public void blankOutFirstContacts(List<Id> FirstContactsNeedingSecondContactNulledOut) {
		List<Contact> ContactsToBeUpdated = new List<Contact>();
		for (Contact ContactsToBeBlanked : [Select Id, SecondContactFirstName__c,SecondContactLastName__c,SecondContactEmail__c from Contact where Id IN :FirstContactsNeedingSecondContactNulledOut]) {	
				ContactsToBeBlanked.SecondContactFirstName__c = null;
				ContactsToBeBlanked.SecondContactLastName__c=null;
				ContactsToBeBlanked.SecondContactEmail__c=null;
				ContactsToBeUpdated.add(ContactsToBeBlanked);
			}
			
		try {
			update ContactsToBeUpdated;
		} catch (System.DmlException e) {		
			for (Integer k = 0; k < e.getNumDml(); k++) {
			 System.debug(e.getDmlMessage(k)); 
			}
		}

	}
	//public method to rename the Households in the Household map
	public void Rename() {
		system.debug('Called Rename');
		Id PreviousHHId;
		Id CurrentHHId;		
		PreviousHHId=null;			
		//loop through hh ids (HouseholdsMap) and put null list in there
		
		for(Id thisHHId : HouseholdsMap.keyset()) {
			List<Contact> contactsInThisHH = new List<Contact>();
			HouseholdsWithContacts.put(thisHHId,contactsInThisHH);
		}
		
		for (Contact c : ContactsInHouseholds) {
			//get this Household's Id
			CurrentHHId = c.ONEN_Household__c;
			
			//pull the list of Contacts for this HH
			List<Contact> contactsInThisHH = HouseholdsWithContacts.get(CurrentHHId);
			//check to see if this contact is already in the list
			boolean contactAleadyInList = false;
			for(Contact thisContact : contactsInThisHH) {
				if (thisContact.Id==c.Id) {
					contactAleadyInList=true;
				}
			}
			
			if(!contactAleadyInList) {
				contactsInThisHH.add(c);
				//put the list of contacts back in
				HouseholdsWithContacts.put(CurrentHHId,contactsInThisHH);	
			}			
		}

		for (ONEN_Household__c hh : HouseholdsMap.values()) {
			List<Contact> allhhcontacts = new List<Contact>();
			Id HHId;
			HHId = hh.Id;
			//set household name
			String HouseholdName;
			Boolean HouseholdNameOverride;
			Boolean GreetingOverride;
			HouseholdNameOverride=false;
			GreetingOverride=false;
			
			//get all the contacts for this Household
			allhhcontacts = HouseholdsWithContacts.get(HHId);

			//if we need to override the name
			if (hh.Override_Household_Name__c!=null) {
				HouseholdNameOverride=true;
			}
			//if we need to override the greeting
			if (hh.Override_Greeting__c!=null) {
				GreetingOverride=true;
			}
			//if Household isn't now empty
			if (allhhcontacts!=null) {
				if (allhhcontacts.size()==1) {	
					if (HouseholdNameOverride) {
						HouseholdName = hh.Override_Household_Name__c;
					} else {
						HouseholdName = allhhcontacts[0].firstname + ' ' + allhhcontacts[0].lastname;
						//system.debug('HH name: ' + HouseholdName);
					}
				} else if(allhhcontacts.size()==2) {
					//name the hh based on the names of the two members	
					if (HouseholdNameOverride) {
						HouseholdName = hh.Override_Household_Name__c;
					} else {	
						if (allhhcontacts[0].lastname==allhhcontacts[1].lastname) {
							HouseholdName = allhhcontacts[0].firstname + ' and ' + allhhcontacts[1].firstname + ' ' + allhhcontacts[1].lastname;	
						} else {
							HouseholdName = allhhcontacts[0].firstname + ' ' + allhhcontacts[0].lastname + ' and ' + allhhcontacts[1].firstname + ' ' + allhhcontacts[1].lastname;	
						}	
					}		
				} else if(allhhcontacts.size()>2) {
					String FamilyName;
					FamilyName='';
					if (HouseholdNameOverride) {
						HouseholdName = hh.Override_Household_Name__c;
					} else {				
						for (Contact thisHouseholdMember : allhhcontacts) {
							if(!FamilyName.contains(thisHouseholdMember.LastName)) {
								if (FamilyName!='') {
									FamilyName += '/' + thisHouseholdMember.LastName;
								} else {
									FamilyName = thisHouseholdMember.LastName;
								}
							}
						}
						HouseholdName = 'The ' + FamilyName + ' Family';
					}
				}
				
				//set greeting
				String HouseholdGreeting;
				HouseholdGreeting='';
				if (GreetingOverride) {
					HouseholdGreeting = hh.Override_Greeting__c;
				} else {
					if (allhhcontacts.size()!=0) {			
						for (Contact thisHouseholdMember : allhhcontacts) {
							if (HouseholdGreeting!='') {
								HouseholdGreeting += ' and ' + thisHouseholdMember.firstname;
							} else {
								HouseholdGreeting = thisHouseholdMember.firstname;
							}
						}
					}
				}
				
				//change the current Household Name
				hh.Name = HouseholdName;
				//change the current Household Greeting
				hh.Greeting__c = HouseholdGreeting;
				//set the new Household Member count to the number of Contacts in the Household
				hh.Member_Count__c = allhhcontacts.size();
				
				String hhMailingStreet = hh.MailingStreet__c;
				String hhMailingCity = hh.MailingCity__c;
				String hhMailingState = hh.MailingState__c;
				String hhMailingPostalCode = hh.MailingPostalCode__c;
				String hhMailingCountry = hh.MailingCountry__c;
				
				boolean householdAddressIsNull = hhMailingStreet==null&&hhMailingCity==null&&hhMailingState==null&&hhMailingPostalCode==null&&hhMailingCountry==null;
				if(householdAddressIsNull){
					for(Contact contactInThisHousehold : allhhcontacts) {
						boolean contactAddressIsNull = contactInThisHousehold.MailingStreet==null&&contactInThisHousehold.MailingCity==null&&contactInThisHousehold.MailingState==null&&contactInThisHousehold.MailingPostalCode==null&&contactInThisHousehold.MailingCountry==null;
				
						if(!contactAddressIsNull) {
							
							hhMailingStreet=contactInThisHousehold.MailingStreet;
							hhMailingCity=contactInThisHousehold.MailingCity;
							hhMailingState=contactInThisHousehold.MailingState;
							hhMailingPostalCode=contactInThisHousehold.MailingPostalCode;
							hhMailingCountry=contactInThisHousehold.MailingCountry;
							
							hh.MailingStreet__c=hhMailingStreet;
							hh.MailingCity__c=hhMailingCity;
							hh.MailingState__c=hhMailingState;
							hh.MailingPostalCode__c=hhMailingPostalCode;
							hh.MailingCountry__c=hhMailingCountry;
						}
					}
				}		
				
				//loop through the Contacts setting all fields

				for(Contact ThisContactForUpdate : allhhcontacts) {
					ThisContactForUpdate.Household_Name__c=HouseholdName;
					ThisContactForUpdate.Household_Greeting__c=HouseholdGreeting;
					ThisContactForUpdate.MailingStreet=hhMailingStreet;
					ThisContactForUpdate.MailingCity=hhMailingCity;
					ThisContactForUpdate.MailingState=hhMailingState;
					ThisContactForUpdate.MailingPostalCode=hhMailingPostalCode;
					ThisContactForUpdate.MailingCountry=hhMailingCountry;
					//add each Contact to the list
					ContactsForUpdate.put(ThisContactForUpdate.Id,ThisContactForUpdate);
				}
				
				
				
			
				
			} else {
				//set the new Household Member count to 0. This will cause deletion
				//of the Household in a trigger
				hh.Member_Count__c = 0;
			}
			
			
		}	
		//update contacts
		if (ContactsForUpdate.size()>0) {
			try {
				update ContactsForUpdate.values();
			} catch (System.DmlException e) {		
				for (Integer k = 0; k < e.getNumDml(); k++) {
				 System.debug(e.getDmlMessage(k)); 
				}
			}
		}
		if (HouseholdsMap.size()>0) {
			try {
				update HouseholdsMap.values();
			} catch (System.DmlException e) {		
				for (Integer k = 0; k < e.getNumDml(); k++) {
				 System.debug(e.getDmlMessage(k)); 
				}
			}
		}
	}
}